home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
src
/
demos
/
GL
/
flight
/
udpbrdcst.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
6KB
|
253 lines
/*
* Copyright 1984-1991, 1992, 1993, 1994, Silicon Graphics, Inc.
* All Rights Reserved.
*
* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
* the contents of this file may not be disclosed to third parties, copied or
* duplicated in any form, in whole or in part, without the prior written
* permission of Silicon Graphics, Inc.
*
* RESTRICTED RIGHTS LEGEND:
* Use, duplication or disclosure by the Government is subject to restrictions
* as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
* and Computer Software clause at DFARS 252.227-7013, and/or in similar or
* successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
* rights reserved under the Copyright Laws of the United States.
*/
/*
* udpbrdcst.c $Revision: 1.7 $
*/
#include <stdio.h>
#include <sys/time.h>
#include "udpbrdcst.h"
#define DOG_MCAST_ADDR "224.0.1.2" /* official address */
#define DEFAULT_TTL 8 /* packet time-to-live */
#define MAX_TTL 32 /* can't go beyond the "site" */
char multicast = 1; /* if 1 use multicast instead of broadcast */
char mcast_ttl = DEFAULT_TTL; /* must be type "char" */
char *mcast_ifaddr = NULL; /* interface address to send to/recv from */
static struct sockaddr_in hostaddr;
/*
* Get a broadcast or multicast socket for the given service.
* Return in "addr" the address to use in a "sendto" so that a message
* can be sent. The socket returned can be used to send a message, as well
* as receive a message. Some interfaces will receive what
* they send, so be prepared to drop messages from yourself.
*/
int
getbroadcast(service, addr)
char *service;
struct sockaddr_in *addr;
{
struct servent *sp;
int fd;
int on = 1;
/* Get our port number */
sp = getservbyname(service, "udp");
if (sp == 0)
{
printf("Can't find udp service \"%s\"\n", service);
return(-2);
}
/* Open the socket */
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0)
{
perror("socket");
return(-1);
}
bzero(addr, sizeof(*addr));
addr->sin_addr.s_addr = INADDR_ANY;
addr->sin_family = AF_INET;
addr->sin_port = sp->s_port;
if (bind(fd, addr, sizeof(*addr)) < 0)
{
perror("bind");
close(fd);
return(-1);
}
if (multicast)
{
struct ip_mreq mreq;
struct in_addr ifaddr;
char mcloop = 0; /* must be type "char" */
/* Disable loopback of mcast packets */
if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &mcloop,
sizeof(mcloop)) < 0){
perror("setsockopt mcast loop");
close(fd);
return(-1);
}
if (mcast_ttl < 0 || mcast_ttl > MAX_TTL)
{
mcast_ttl = DEFAULT_TTL;
}
if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, &mcast_ttl,
sizeof(mcast_ttl)) < 0)
{
perror("setsockopt mcast ttl");
close(fd);
return(-1);
}
/* Change the default interface (only useful on gateways) */
if (mcast_ifaddr != NULL)
{
struct hostent *hp;
ifaddr.s_addr = inet_addr(mcast_ifaddr);
if (ifaddr.s_addr == (unsigned)-1)
{
hp = gethostbyname(mcast_ifaddr);
if (hp)
{
bcopy(hp->h_addr, (caddr_t)&ifaddr, hp->h_length);
}
else
{
fprintf(stderr, "Can't find IP address for '%s'\n",
mcast_ifaddr);
close(fd);
return(-1);
}
}
if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, &ifaddr,
sizeof(ifaddr)) < 0)
{
perror("Can't send mcasts on the specified interface");
close(fd);
return(-1);
}
mreq.imr_interface = ifaddr;
}
else
{
mreq.imr_interface.s_addr = INADDR_ANY;
}
mreq.imr_multiaddr.s_addr = addr->sin_addr.s_addr =
inet_addr(DOG_MCAST_ADDR);
if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq,
sizeof(mreq)) < 0)
{
perror("Can't add mcast address");
fprintf(stderr,
"Can't use multicast mode, reverting to broadcast mode.\n");
multicast = 0; /* fall through */
}
}
if (!multicast)
{
addr->sin_addr.s_addr = INADDR_BROADCAST;
if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0)
{
perror("setsockopt");
close(fd);
return(-1);
}
}
if (ioctl(fd, FIONBIO, &on) < 0) /* Turn on non-blocking I/O */
{
perror("ioctl");
close(fd);
return(-1);
}
(void) gethostaddr(&hostaddr);
return(fd);
}
/*
* Get host internet address
*/
int
gethostaddr(addr)
struct sockaddr_in *addr;
{
char hostname[100];
struct hostent *hp;
if (gethostname(hostname, sizeof(hostname)) < 0)
return(-1);
hp = gethostbyname(hostname);
if (!hp)
return(-1);
addr->sin_family = AF_INET;
addr->sin_port = 0;
bcopy(hp->h_addr, &addr->sin_addr, sizeof(addr->sin_addr));
return(0);
}
/*
* sendbroadcast
*/
int
sendbroadcast(broadcastsocket, message, messagelength, addr)
int broadcastsocket;
char * message;
int messagelength;
struct sockaddr_in *addr;
{
return(sendto(broadcastsocket, message, messagelength, 0, addr,
sizeof(*addr)));
}
/*
* recvbroadcast
*/
int
recvbroadcast(broadcastsocket, message, messagelength, ignoreown)
int broadcastsocket;
char *message;
int messagelength;
int ignoreown;
{
struct sockaddr_in fromaddr;
int fromaddrlength = sizeof(fromaddr);
int charcount;
do
{
charcount=recvfrom(broadcastsocket, message, messagelength, 0,
&fromaddr, &fromaddrlength);
if (charcount < 0)
{
if (errno == EWOULDBLOCK)
return(0);
else
{
perror("recvbroadcast");
exit(-1);
}
}
if (charcount == 0)
break;
} while (ignoreown &&
(fromaddr.sin_addr.s_addr == hostaddr.sin_addr.s_addr));
return(charcount);
}